<template>
  <div>
    <el-button @click="handleCheck">选择</el-button>
    <el-slider
      :min="-180"
      :max="180"
      v-model="hueVal"
      @input="handleChange"
    ></el-slider>
    <div>
      <canvas ref="canvasRef" id="result_canvas"></canvas>
    </div>
  </div>
</template>

<script setup lang="ts">
// import { useFileDialog } from '@vueuse/core'
import * as ti from 'taichi.js'
import { onMounted, ref } from 'vue'

import testImage from '@/assets/222.jpg'
const hueVal = ref(0)
let canvas: ti.Canvas | null = null
let kernel: Function | null = null
const handleChange = async () => {
  if (!kernel) return
  await kernel(hueVal.value)
  canvas?.setImage(pixels)
}
const canvasRef = ref<HTMLCanvasElement>()

// const { files, open, reset, onChange } = useFileDialog({
//   accept: 'image/*',
// })
const size = ref({
  width: 0,
  height: 0,
})
let pixels = null
onMounted(async () => {
  await initTi()
  const texture = await initTexture()
  const width = texture.texture.width
  const height = texture.texture.height
  size.value = {
    width,
    height,
  }
  pixels = ti.Vector.field(4, ti.f32, [width, height])
  ti.addToKernelScope({
    pixels,
    texture,
    width,
    height,
    getCoords,
    rgbToHsv,
    hsvToRgb,
  })
  initCanvas()

  kernel = ti.kernel(`(hue) => {
    for (const I of ti.ndrange(width, height)) {
      const i = I[0]
      const j = I[1]
      const coords = getCoords([i, j], height)
      const texelValue = ti.textureLoad(texture, coords)
      const hsv = rgbToHsv([
        texelValue[0] * 255,
        texelValue[1] * 255,
        texelValue[2] * 255,
      ])
      hsv[0] = hsv[0] + hue
      if (hsv[0] < 0) hsv[0] += 360
      if (hsv[0] >= 360) hsv[0] -= 360
      const rgb = hsvToRgb(hsv)
      pixels[(i, j)] = [rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1]
    }
  }`)
  if (!kernel) return
  await kernel(hueVal.value)
  canvas?.setImage(pixels)
})
const handleCheck = () => {
  open()
}
const getCoords = (v, height) => [v.x, height - v.y]
const rgbToHsv = (arr) => {
  let h = ti.f32(0)
  let s = ti.f32(0)
  let v = ti.f32(0)
  const r = arr[0]
  const g = arr[1]
  const b = arr[2]
  const max = ti.max(ti.max(r, g), b)
  const min = ti.min(ti.min(r, g), b)
  // arr.sort(function (a, b) {
  //   return a - b
  // })
  // const max = arr[2]
  // const min = arr[0]
  v = max / 255
  if (max === 0) {
    s = 0
  } else {
    s = 1 - min / max
  }
  if (max === min) {
    h = 0
  } else if (max === r && g >= b) {
    h = 60 * ((g - b) / (max - min)) + 0
  } else if (max === r && g < b) {
    h = 60 * ((g - b) / (max - min)) + 360
  } else if (max === g) {
    h = 60 * ((b - r) / (max - min)) + 120
  } else if (max === b) {
    h = 60 * ((r - g) / (max - min)) + 240
  }
  h = ti.i32(h)
  return [h, s, v]
}
const hsvToRgb = (arr) => {
  const h = arr[0]
  const s = ti.max(0, arr[1])
  const v = arr[2]
  let r = ti.f32(0)
  let g = ti.f32(0)
  let b = ti.f32(0)
  const i = ti.i32((h / 60) % 6)
  const f = h / 60 - i
  const p = v * (1 - s)
  const q = v * (1 - f * s)
  const t = v * (1 - (1 - f) * s)
  if (i === 0) {
    r = v
    g = t
    b = p
  }
  if (i === 1) {
    r = q
    g = v
    b = p
  }
  if (i === 2) {
    r = p
    g = v
    b = t
  }
  if (i === 3) {
    r = p
    g = q
    b = v
  }
  if (i === 4) {
    r = t
    g = p
    b = v
  }
  if (i === 5) {
    r = v
    g = p
    b = q
  }
  r = ti.i32(r * 255.0)
  g = ti.i32(g * 255.0)
  b = ti.i32(b * 255.0)
  return [r, g, b]
}
const initTi = async () => {
  await ti.init()
}
const initTexture = async () => {
  const url = testImage
  const texture = await ti.Texture.createFromURL(url)
  return texture
}
const initCanvas = () => {
  const htmlCanvas = canvasRef.value
  if (!htmlCanvas) return
  htmlCanvas.width = size.value.width
  htmlCanvas.height = size.value.height
  canvas = new ti.Canvas(htmlCanvas)
}
export interface IFilterGroup {
  brightness: number
  contrast: number
  hue: number
  saturate: number
  expousre: number
  highlight: number
  shadow: number
}
// const adjustBrightnessContrast = (
//   dataSrc: Uint8ClampedArray,
//   dataDst: Uint8ClampedArray,
//   filterGroup: IFilterGroup,
// ) => {
//   console.time('亮度对比度耗时')
//   const B = filterGroup.brightness
//   const C = filterGroup.contrast
//   const absB = Math.abs(B)
//   const tempB = absB / 50.0

//   if (B === 0 && C === 0) {
//     copySrctoDst(dataSrc, dataDst)
//     return
//   }

//   let gamma, gamma1
//   if (absB <= 50) {
//     gamma = 0.76 * tempB + 1
//     gamma1 = 0.12 * tempB + 1
//   } else if (absB <= 100) {
//     gamma = 0.94 * tempB + 0.82
//     if (B < 0) {
//       gamma1 = 0.01 * tempB + 1.11
//     } else {
//       gamma1 = 0.07 * tempB + 1.05
//     }
//   } else {
//     gamma = 1.8 * tempB - 0.9
//     if (B < 0) {
//       gamma1 = 0.005 * tempB + 1.12
//     } else {
//       gamma1 = 0.18 * tempB + 0.83
//     }
//   }

//   if (B < 0) {
//     gamma = 1.0 / gamma
//     gamma1 = 1.0 / gamma1
//   }

//   const la = parseInt(((C / 100.0) * 0.006 * (1 << 20)).toString())
//   let table = new Array(256)
//   for (let i = 0; i < 256; i++) {
//     let lR = Math.round(
//       255 *
//         Math.pow(
//           (255 - 255 * Math.pow((255 - i) / 255.0, gamma)) / 255.0,
//           gamma1,
//         ),
//     )
//     if (lR < 0) lR = 0
//     if (lR > 255) lR = 255

//     if (lR <= 128) {
//       lR = lR + (((lR - 128) * lR * la) >> 20)
//       if (lR < 0) lR = 0
//       if (lR > 255) lR = 255
//     } else {
//       lR = lR + (((lR - 128) * (255 - lR) * la) >> 20)
//       if (lR < 0) lR = 0
//       if (lR > 255) lR = 255
//     }

//     table[i] = lR
//   }

//   for (let i = 0; i < dataDst.length; i += 4) {
//     dataDst[i] = table[dataSrc[i]]
//     dataDst[i + 1] = table[dataSrc[i + 1]]
//     dataDst[i + 2] = table[dataSrc[i + 2]]
//   }
//   console.timeEnd('亮度对比度耗时')

//   table = []
// }
</script>

<style scoped lang="scss"></style>
